//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<DataManager.cpp>
///	@path	~/src/database/
///	@date	2007/11/21
///	@desc	Data manager.

#include "config/config.h"

#include "lib/system/thread_debug.h"

#include "database/DataManager.h"
#include "database/store/IFile.h"
#include "database/xdata/CTreeData.h"
#include "database/xdata/CDirectoryData.h"

namespace xeres {

	// ctor
	DataManager::DataManager( void )
	{
		// cache nodes in data system
	}

	// dtor
	DataManager::~DataManager( void )
	{
	}

	// Initialize
	bool DataManager::Initialize( void )
	{
		if( m_rootEntry.IsValid() )
		{
			TRACE_ERROR( _S("DataManager::Initialize: DataManager is initialized.") );
			return false;
		}
		m_rootEntry =  new CTreeData( _S("") );
		return true;
	}

	// IsInitialized
	bool DataManager::IsInitialized( void )
	{
		return m_rootEntry.IsValid();
	}

	// Finalize
	void DataManager::Finalize( void )
	{
		m_rootEntry = NULL;
	}

	void DataManager::AddDataEntryRoot( RefWeak<IData> entry )
	{
		TRACK_FUNCTION_SCOPE();
		RUNNING_ON_THREAD( _S("main|tick|!pool*|!_render") );

		// validate
		XS_ASSERT( m_rootEntry.IsValid() );
		m_rootEntry->AddChild( entry );
	}

	RefPass<IData> DataManager::OpenData( const WString& path , bool create_non_exists )
	{
		if( m_rootEntry.IsValid() )
		{
			if( ( path.size() == 1 ) && ( path[0] == '.' || path[0] == '/' ) )
			{
				return m_rootEntry;
			}

			return m_rootEntry->OpenData( path , create_non_exists );
		}
		else
		{
			TRACE_WARNING( _S("DataManager::OpenData: Root data entry is not specified.") );
			return NULL;
		}
	}

	// OpenFile
	RefPass<IFile> DataManager::OpenFile( const WString& path )
	{
		if( m_rootEntry.IsValid() )
		{
			// clamp to last dir
			size_t last_split = path.find_last_of( '/' );
			WString dir = path.substr( 0 , last_split );
			WString file = path.substr( last_split + 1 );

			Ref<CDirectoryData> directory = m_rootEntry->OpenData( dir );
			if( directory.IsValid() )
			{
				return directory->OpenFile( file );
			}
			return NULL;
		}
		else
		{
			TRACE_WARNING( _S("DataManager::OpenFile: Root data entry is not specified.") );
			return NULL;
		}
	}

	// OpenIStream
	struct IStream * DataManager::OpenIStream( const WString& path )
	{
		if( m_rootEntry.IsValid() )
		{
			// clamp to last dir
			size_t last_split = path.find_last_of( '/' );
			WString dir = path.substr( 0 , last_split );
			WString file = path.substr( last_split + 1 );

			Ref<CDirectoryData> directory = m_rootEntry->OpenData( dir );
			if( directory.IsValid() )
			{
				return directory->OpenIStream( file );
			}
			return NULL;
		}
		else
		{
			TRACE_WARNING( _S("DataManager::OpenIStream: Root data entry is not specified.") );
			return NULL;
		}
	}
	// LoadBinaryFromFile
	RefPass<IBuffer> DataManager::LoadBinaryFromFile( const WString& path )
	{
		Ref<IFile> file = OpenFile( path );
		if( file.IsNull() )
		{
			TRACE_ERROR( _S("DataManager::LoadBinaryFromFile: Failed to open file." ) );
			return NULL;
		}

		DataInfo info;
		XS_VERIFY( file->GetInfo( info ) );

		// more than 5 Mb cache give a warning.
		if( info.m_size >= 5 * 1024 * 1024 )
		{
			TRACE_WARNING( _S("DataManager::LoadBinaryFromFile: Try to load massive data to memory buffer could cause performance problem(<%s>).") ,
				path.c_str() );
		}

		size_t size = (size_t)info.m_size;
		RefPass<IBuffer> buffer = IBuffer::Create( size );
		size_t read = 0;
		read = file->Read( buffer->GetData() , size );
		if( read == 0 )
		{
			return NULL;
		}
		return buffer;
	}
	
} // namespace xeres
